package com.xingda.packing.dmds.minitor.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xingda.packing.dmds.common.DateUtils;
import com.xingda.packing.dmds.config.appset.AppSetParam;
import com.xingda.packing.dmds.enums.AlarmTriggerType;
import com.xingda.packing.dmds.enums.BoxLocationNo;
import com.xingda.packing.dmds.enums.TaskUploadState;
import com.xingda.packing.dmds.enums.TaskUploadType;
import com.xingda.packing.dmds.events.EventCreater;
import com.xingda.packing.dmds.events.dto.ItemPositionParam;
import com.xingda.packing.dmds.events.dto.PackageFloorInfoParam;
import com.xingda.packing.dmds.http.PackageSaveHttp;
import com.xingda.packing.dmds.http.PackinvweighHttp;
import com.xingda.packing.dmds.minitor.dto.LayerDto;
import com.xingda.packing.dmds.minitor.dto.LayerListDto;
import com.xingda.packing.dmds.minitor.dto.PkTaskUploadDto;
import com.xingda.packing.dmds.minitor.entity.PkTask;
import com.xingda.packing.dmds.minitor.entity.PkTaskInfo;
import com.xingda.packing.dmds.minitor.entity.PkTaskUpload;
import com.xingda.packing.dmds.minitor.entity.PkWheel;
import com.xingda.packing.dmds.minitor.mapper.PkTaskMapper;
import com.xingda.packing.dmds.minitor.mapper.PkTaskUploadMapper;
import com.xingda.packing.dmds.minitor.service.IPkTaskInfoService;
import com.xingda.packing.dmds.minitor.service.IPkTaskService;
import com.xingda.packing.dmds.minitor.service.IPkTaskUploadService;
import com.xingda.packing.dmds.minitor.service.IPkWheelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service("pkTaskUploadDMDSService")
public class PkTaskUploadImpl extends ServiceImpl<PkTaskUploadMapper, PkTaskUpload> implements IPkTaskUploadService {

    @Resource
    IPkTaskService pkTaskService;

    @Resource
    IPkTaskInfoService pkTaskInfoService;
    @Resource
    private PkTaskMapper pkTaskMapper;
    @Resource
    private PkTaskUploadMapper pkTaskUploadMapper;

    @Resource
    IPkWheelService pkWheelService;
    @Value("${com.xingda.pkRobotdoc}")
    private String pkRobotdoc;
    @Resource
    EventCreater eventCreater;


    @Override
    public List<LayerListDto> getList() {
        List<LayerListDto> layerListDtoList = new ArrayList<>();
        LambdaQueryWrapper<PkTask> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.isNull(PkTask::getEndTime).eq(PkTask::getType, 1);
        List<PkTask> pkTasks = pkTaskMapper.selectList(lambdaQueryWrapper);
        for (PkTask pkTask : pkTasks) {
            LayerListDto layerListDto = new LayerListDto();
            layerListDto.setBoxNo(pkTask.getBoxNo());
            layerListDto.setCustomerName(pkTask.getCustomerName());
            layerListDto.setWheelTypeName(pkTask.getWheelTypeName());
            layerListDto.setStartTime(pkTask.getStartTime());
            List<LayerDto> layers = new ArrayList<>();
            LambdaQueryWrapper<PkTaskUpload> pkTaskUploadLambdaQueryWrapper = new LambdaQueryWrapper<>();
            pkTaskUploadLambdaQueryWrapper.eq(PkTaskUpload::getPkTaskId, pkTask.getId());
            List<PkTaskUpload> pkTaskUploads = pkTaskUploadMapper.selectList(pkTaskUploadLambdaQueryWrapper);
            for (PkTaskUpload pkTaskUpload : pkTaskUploads) {
                LayerDto layerDto = new LayerDto();
                layerDto.setLayer(pkTaskUpload.getLayer());
                layerDto.setUpTime(pkTaskUpload.getUpTime());
                layerDto.setMessage(pkTaskUpload.getMessage());
                layerDto.setState(TaskUploadState.getById(pkTaskUpload.getState()).getDesc());
                layers.add(layerDto);
            }
            layerListDto.setLayers(layers);
            layerListDtoList.add(layerListDto);
        }
        return layerListDtoList;
    }

    @Override
    public void triggerUploadAlarm(int area, int boxLocationNo, boolean value) {
        if (boxLocationNo == 1) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_1_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 2) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_2_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 3) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_3_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 4) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_4_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 5) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_5_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 6) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_6_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 7) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_7_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 8) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_8_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 9) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_9_UPLOAD_FAIL, value, area);
        } else if (boxLocationNo == 10) {
            eventCreater.createTriggerAlarm(AlarmTriggerType.PRODUCT_BOX_LOCATION_10_UPLOAD_FAIL, value, area);
        }
    }

    @Override
    public List<PkTaskUploadDto> gePkTaskUploadDtoBy(int taskId) {

        LambdaQueryWrapper<PkTaskUpload> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PkTaskUpload::getPkTaskId, taskId);
        queryWrapper.orderByAsc(PkTaskUpload::getLayer);

        List<PkTaskUpload> list = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        List<PkTaskUploadDto> pkTaskUploadDtoList = new ArrayList<>();
        for (PkTaskUpload pkTaskUpload : list) {
            PkTaskUploadDto dto = new PkTaskUploadDto();
            dto.setLayer(pkTaskUpload.getLayer());
            dto.setState(pkTaskUpload.getState());
            pkTaskUploadDtoList.add(dto);
        }
        return pkTaskUploadDtoList;
    }

    @Override
    public void saveOrUpdate(int taskId, int layer, int state, String param, int type, String message) {
        LambdaQueryWrapper<PkTaskUpload> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PkTaskUpload::getPkTaskId, taskId).eq(PkTaskUpload::getLayer, layer);

        List<PkTaskUpload> list = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            PkTaskUpload pkTaskUpload = new PkTaskUpload();
            pkTaskUpload.setLayer(layer);
            pkTaskUpload.setParam(param);
            pkTaskUpload.setMessage(message);
            pkTaskUpload.setPkTaskId(taskId);
            pkTaskUpload.setState(state);
            pkTaskUpload.setUpTime(new Date());
            this.baseMapper.insert(pkTaskUpload);
        } else {
            PkTaskUpload pkTaskUpload = list.get(0);
            pkTaskUpload.setParam(param);
            pkTaskUpload.setMessage(message);
            pkTaskUpload.setState(state);
            pkTaskUpload.setUpTime(new Date());
            this.baseMapper.updateById(pkTaskUpload);
        }
    }

    @Transactional
    @Override
    public void upload(int taskId, int layer) {

        PkTask pkTask = pkTaskService.getById(taskId);

        if (layer == 0) {
            uploadPackaging(pkTask, layer);
        } else if (layer > 0) {
            uploadLayerInfo(pkTask, layer);
        }
    }

    /**
     * 上传包装物
     */
    private void uploadPackaging(PkTask pkTask, int layer) {
        JSONObject resultJson = PackinvweighHttp.save(pkTask.getPkPacking());
        TaskUploadState state = TaskUploadState.FAIL;
        if (CollectionUtils.isEmpty(resultJson) && resultJson.getIntValue("code") == 0) {
            state = TaskUploadState.SUCCESS;
        }
        saveOrUpdate(pkTask.getId(), layer, state.getNumber(), null, TaskUploadType.MANUAL.getNumber(), resultJson.getString("msg"));
    }

    /**
     * 上传层信息
     */
    private void uploadLayerInfo(PkTask pkTask, int layer) {
        PackageFloorInfoParam packageFloorInfoParam = new PackageFloorInfoParam();
        packageFloorInfoParam.setLayer(layer);
        packageFloorInfoParam.setPacktime(DateUtils.getNowDate());
        packageFloorInfoParam.setPkCalbody(pkTask.getPkCalbody());
        packageFloorInfoParam.setPkCorp(pkTask.getPkCorp());
        packageFloorInfoParam.setPkDeptdoc(pkTask.getPkDeptDoc());
        packageFloorInfoParam.setPkPacking(pkTask.getPkPacking());
        List<ItemPositionParam> items = new ArrayList<>();
        LambdaQueryWrapper<PkTaskInfo> pkTaskInfoQueryWrapper = Wrappers.lambdaQuery();
        pkTaskInfoQueryWrapper.eq(PkTaskInfo::getTaskId, pkTask.getId()).eq(PkTaskInfo::getLayer, layer).orderByAsc(PkTaskInfo::getPutTime);
        List<PkTaskInfo> pkTaskInfoList = pkTaskInfoService.list(pkTaskInfoQueryWrapper);
        if (CollectionUtils.isEmpty(pkTaskInfoList) || pkTaskInfoList.size() < pkTask.getFloorCount()) {
            log.warn("本层数量未达到要求数量，无法上传！任务ID：{}，层号：{}", pkTask.getId(), layer);
            return;
        }
        List<Integer> wheelIds = pkTaskInfoList.stream().map(PkTaskInfo::getWheelId).collect(Collectors.toList());

        LambdaQueryWrapper<PkWheel> pkWheelQueryWrapper = Wrappers.lambdaQuery();
        pkWheelQueryWrapper.in(PkWheel::getId, wheelIds);

        List<PkWheel> pkWheelList = pkWheelService.list(pkWheelQueryWrapper);

        //修改轮子顺序按放置顺序上传(从里到外1-12)
        List<Integer> sortList = AppSetParam.wheel_sort_index;
        int subSize = !CollectionUtils.isEmpty(pkTaskInfoList) ? pkTaskInfoList.size() : 0;
        //排序后集合
        List<PkWheel> pkWheelSortList = new ArrayList<>();
        //先排序后集合填充null
        pkWheelList.forEach(x -> pkWheelSortList.add(null));
        for (int j = 0; j < pkTaskInfoList.size(); j++) {
            PkTaskInfo thisPkTaskInfo = subSize - 1 >= j ? pkTaskInfoList.get(j) : null;
            if (Objects.isNull(thisPkTaskInfo)) {
                log.info("装箱层详细信息获取出错！");
                return;
            }
            Optional<PkWheel> pkWheelOpt = pkWheelList.stream().filter(thisPkWheel -> thisPkWheel.getId() == thisPkTaskInfo.getWheelId()).findFirst();
            if (!pkWheelOpt.isPresent()) {
                log.info("装箱层详细信息获取出错！-工字轮id-{}未找到信息！", thisPkTaskInfo.getWheelId());
                return;
            }
            PkWheel thisPkWheel = pkWheelOpt.get();
            int sortIndex = sortList.get(j);
            pkWheelSortList.set(sortIndex, thisPkWheel);
        }

        for (int i = 0; i < pkWheelSortList.size(); i++) {
            PkWheel pkWheel = pkWheelSortList.get(i);
            ItemPositionParam itemPositionParam = new ItemPositionParam();
            itemPositionParam.setPkIntermediate(pkWheel.getWheelPk());
            itemPositionParam.setPosition(i + 1);
            itemPositionParam.setHwheelbarcode(pkWheel.getBarCode());
            items.add(itemPositionParam);
        }
        packageFloorInfoParam.setPkRobotdoc(pkRobotdoc);
        packageFloorInfoParam.setSolderjointcount(pkWheelList.stream().map(PkWheel::getSolder).reduce(0, Integer::sum));
        packageFloorInfoParam.setTorsionsum(pkWheelList.stream().map(PkWheel::getTorqueValue).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        packageFloorInfoParam.setItems(items);
        JSONObject resultJson = PackageSaveHttp.save(packageFloorInfoParam);
        TaskUploadState state = TaskUploadState.FAIL;
        if (!CollectionUtils.isEmpty(resultJson) && resultJson.getIntValue("code") == 0) {
            state = TaskUploadState.SUCCESS;
            triggerUploadAlarm(pkTask.getBoxLocationId() > 10 ? 2 : 1, BoxLocationNo.getById(pkTask.getBoxLocationId()).getNo(), false);
        }
        saveOrUpdate(pkTask.getId(), layer, state.getNumber(), JSONObject.toJSONString(packageFloorInfoParam), TaskUploadType.MANUAL.getNumber(), resultJson.getString("msg"));
    }

    @Override
    public PkTaskUpload getByTaskIdAndLayer(int taskId, int layer) {
        LambdaQueryWrapper<PkTaskUpload> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PkTaskUpload::getPkTaskId, taskId)
                .eq(PkTaskUpload::getLayer, layer)
        ;
        List<PkTaskUpload> list = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public boolean isUploadSuccess(int taskId, int layer) {

        PkTaskUpload pkTaskUpload = getByTaskIdAndLayer(taskId, layer);

        if (Objects.nonNull(pkTaskUpload)) {
            return pkTaskUpload.getState() == TaskUploadState.SUCCESS.getNumber();
        }

        return false;
    }

}
